////////////////////////////////////////////////////////////////////////////////
/// @file    core_delay.c
/// @author  AE TEAM
/// @brief   THIS FILE PROVIDES ALL THE SYSTEM FIRMWARE FUNCTIONS.
////////////////////////////////////////////////////////////////////////////////
/// @attention
///
/// THE EXISTING FIRMWARE IS ONLY FOR REFERENCE, WHICH IS DESIGNED TO PROVIDE
/// CUSTOMERS WITH CODING INFORMATION ABOUT THEIR PRODUCTS SO THEY CAN SAVE
/// TIME. THEREFORE, MINDMOTION SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT OR
/// CONSEQUENTIAL DAMAGES ABOUT ANY CLAIMS ARISING OUT OF THE CONTENT OF SUCH
/// HARDWARE AND/OR THE USE OF THE CODING INFORMATION CONTAINED HEREIN IN
/// CONNECTION WITH PRODUCTS MADE BY CUSTOMERS.
///
/// <H2><CENTER>&COPY; COPYRIGHT MINDMOTION </CENTER></H2>
////////////////////////////////////////////////////////////////////////////////


// Define to prevent recursive inclusion

#include "core_delay.h"
#include "main.h"



#if USE_DWT_DELAY


#define  DWT_CR      *(__IO uint32_t *)0xE0001000
#define  DWT_CYCCNT  *(__IO uint32_t *)0xE0001004
#define  DEM_CR      *(__IO uint32_t *)0xE000EDFC


#define  DEM_CR_TRCENA                   (1 << 24)
#define  DWT_CR_CYCCNTENA                (1 <<  0)

////////////////////////////////////////////////////////////////////////////////
/// @brief  Initialization timestamp
/// @param  None
/// @retval None
/// @note   Before using the delay function, you must call this function
////////////////////////////////////////////////////////////////////////////////
void CPU_TS_TmrInit(void)
{

    DEM_CR |= (uint32_t)DEM_CR_TRCENA;


    DWT_CYCCNT = (uint32_t)0u;


    DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief  Read current timestamp
/// @param  None
/// @retval The current timestamp, which is the value of the DWT_CYCCNT register
////////////////////////////////////////////////////////////////////////////////
uint32_t CPU_TS_TmrRd(void)
{
    return ((uint32_t)DWT_CYCCNT);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief  Use CPU's internal count to achieve precise delay, 32-bit counter
/// @param  us : Delay, unit 1 us
/// @retval None
/// @note   Before using this function, you must first call the CPU_TS_TmrInit
///         function to enable the counter, or enable the macro
///         CPU_TS_INIT_IN_DELAY_FUNCTION.
///         The maximum delay value is 8 seconds, which is 8*1000*1000
////////////////////////////////////////////////////////////////////////////////
void CPU_TS_Tmr_Delay_US(__IO uint32_t us)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;


#if (CPU_TS_INIT_IN_DELAY_FUNCTION)

    CPU_TS_TmrInit();
#endif

    ticks = us * (GET_CPU_ClkFreq() / 1000000);
    tcnt = 0;
    told = (uint32_t)CPU_TS_TmrRd();

    while(1) {
        tnow = (uint32_t)CPU_TS_TmrRd();
        if(tnow != told) {

            if(tnow > told) {
                tcnt += tnow - told;
            }

            else {
                tcnt += UINT32_MAX - told + tnow;
            }

            told = tnow;


            if(tcnt >= ticks)break;
        }
    }
}

#endif

/*********************************************END OF FILE**********************/
